﻿#include <algorithm>
#include <gtest/gtest.h>
#include <iostream>
#include <vector>

#include <xy/math/diff.h>

using namespace std;
using namespace xy;
using namespace xy::math;

// 测试 Jacobian 函数
TEST(TestDifferential, diff)
{
    auto f = [](const vecxd &x) -> double { return 2 * sin(x[0]) + cos(x[1]); };
    auto g = [](const vecxd &x) -> vecxd { return {2 * sin(x[0]) + cos(x[1]), -2 * cos(x[0]) + sin(x[1])}; };

    auto fj = diff::jacobian<double>(f, {0, 0});
    auto gj = diff::jacobian<vecxd>(g, {0, 0});

    matxd fJ(1, 2);
    fJ(0, 0) = 2;
    fJ(0, 1) = 0;
    EXPECT_LT((fJ - fj).norm(), numeric::distance);

    matxd gJ(2, 2);
    gJ(0, 0) = 2;
    gJ(0, 1) = 0;
    gJ(1, 0) = 0;
    gJ(1, 1) = 1;
    // std::cout << gJ << std::endl;
    // std::cout << gj << std::endl;
    EXPECT_LT((gJ - gj).norm(), numeric::distance);
}

TEST(TestDifferential, hessen)
{
    auto f = [](const vecxd &x) -> double { return 10 * sin(x[0]) + 3 * cos(x[1]); };
    auto h = diff::hessian(f, {0, 0});
    std::cout << h << std::endl;
}